package com.itlong.cloud.push.message;


import com.itlong.cloud.POJO.PO.OperateUserInfoPO;
import com.itlong.cloud.POJO.VO.property.PropertyUserCacheVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.*;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.websocketx.*;
import org.jboss.netty.util.CharsetUtil;

import java.util.HashMap;
import java.util.Map;

import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.HOST;
import static org.jboss.netty.handler.codec.http.HttpHeaders.isKeepAlive;
import static org.jboss.netty.handler.codec.http.HttpHeaders.setContentLength;
import static org.jboss.netty.handler.codec.http.HttpMethod.GET;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * <desc>
 * websocket中处理业务逻辑类.
 * </desc>
 *
 * @createDate 2018/7/5
 */
public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {

    private static final String WEBSOCKET_PATH = "/websocket";
    private WebSocketServerHandshaker handshaker;
    public static final Map<String,Object> tokenMap = new HashMap<>();

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {

        Object msg = e.getMessage();
        if (msg instanceof HttpRequest) {
            handleHttpRequest(ctx, (HttpRequest) msg);
        } else if (msg instanceof WebSocketFrame) {
            handleWebSocketFrame(ctx, (WebSocketFrame) msg);
        }
        try {
            RedisService  redisService = (RedisService) SpringContextUtils.getBean("redisServiceImpl");
            UserTokenKey userTokenKey = (UserTokenKey) SpringContextUtils.getBean("userTokenKey");
            Map<String,Object> param = JsonUtil.toObject(JsonUtil.toJSON(msg), HashMap.class);
            Map<String, Object> text = param.get("text") != null ? JsonUtil.toObject(param.get("text").toString(), HashMap.class) : null;
            Integer type  = (Integer)text.get("type");
            String token = text.get("token").toString();
            if(type ==1){
                //物业
                String userId = UserTokenUtil.tokenDecryptBySSO(token, PlatformConstants.PROPERTY_USER_TOKEN_KEY);
                String cacheKey = String.format("%s%s", RedisConstant.PROPERTY_USER_REDIS_KEY, userId);
                String tokenKey = String.format("%s%s", RedisConstant.PROPERTY_USER_TOKEN_REDIS_CACHE_KEY, userId);
                PropertyUserCacheVO propertyUserCacheVO = (PropertyUserCacheVO)redisService.getObject(cacheKey, PropertyUserCacheVO.class);
                if(propertyUserCacheVO != null ){
                    redisService.set(tokenKey,RedisConstant.PROPERTY_USER_TOKEN_REDIS_CACHE_TIME,"1");
                    tokenMap.put("userId",type);
                }
            }else if(type ==2){
                String userId = UserTokenUtil.tokenDecryptBySSO(token, userTokenKey.getUserTokenKey());
                String cacheKey = String.format("%s%s", RedisConstant.OPERATE_REDIS_USER_KEY, userId);
                String tokenKey = String.format("%s%s", RedisConstant.OPERATE_REDIS_USER_TOKEN_CACHE_KEY, userId);
                //运营
                OperateUserInfoPO userInfoPO = (OperateUserInfoPO)redisService.getObject(cacheKey, OperateUserInfoPO.class);
                if(userInfoPO != null){
                    redisService.set(tokenKey,RedisConstant.OPERATE_REDIS_USER_TOKEN_CACHE_TIME,"1");
                    tokenMap.put("userId",type);
                }
            }
        }catch (Exception error){

        }
    }
    @Override
    public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        String uuid = ctx.getChannel().getId().toString();
        GatewayService.addGatewayChannel(uuid, ctx.getChannel());
        System.out.println(GatewayService.getGatewayChannel(uuid));
    }


    public static void main(String[] args) {
        String token = "+SJ2jPD8Y4ZxIJziG3nsUaQJR+khgQ8oZM0Nj2gef5mwQimZmZNChI15f/1EEdoyqEPi+4ZgGrEaKVbGuriCMkTZP8gNV1F9DegUmId0thg=";
        System.out.println(UserTokenUtil.tokenDecryptBySSO(token, PlatformConstants.PROPERTY_USER_TOKEN_KEY));
    }

    private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
        // Allow only GET methods.
        if (req.getMethod() != GET) {
            sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
            return;
        }

        if ("/".equals(req.getUri())) {
            HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK);
            return;
        }
        if ("/favicon.ico".equals(req.getUri())) {
            HttpResponse res = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND);
            sendHttpResponse(ctx, req, res);
            return;
        }

        // Handshake
        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
                getWebSocketLocation(req), null, false);
        handshaker = wsFactory.newHandshaker(req);
        if (handshaker == null) {
            wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
        } else {
            handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
        }
    }

    private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
        // Check for closing frame
        if (frame instanceof CloseWebSocketFrame) {
            handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
            return;
        }
        if (frame instanceof PingWebSocketFrame) {
            ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));
            return;
        }
        if (!(frame instanceof TextWebSocketFrame)) {
            throw new UnsupportedOperationException(
                    String.format("%s frame types not supported", frame.getClass().getName()));
        }

        // Send the uppercase string back.
        String request = ((TextWebSocketFrame) frame).getText();
        System.err.println(String.format("Channel %s received %s", ctx.getChannel().getId(), request));
//        ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
    }

    private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {

        if (res.getStatus().getCode() != 200) {
            res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
            setContentLength(res, res.getContent().readableBytes());
        }

        ChannelFuture f = ctx.getChannel().write(res);
        if (!isKeepAlive(req) || res.getStatus().getCode() != 200) {
            f.addListener(ChannelFutureListener.CLOSE);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        e.getCause().printStackTrace();
        e.getChannel().close();
    }

    private static String getWebSocketLocation(HttpRequest req) {
        String location =  req.headers().get(HOST) + WEBSOCKET_PATH;
        if (WebSocketServer.SSL) {
            return "wss://" + location;
        } else {
            return "ws://" + location;
        }
    }
}